package com.ruoyi.common.tools.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * id生成器，yyyyMMddHHmmss(b)(num)
 *
 * @author cc
 */
public class SerialGenerator {
    private final static int MAX_SEQUENCE_NUM = 99;

    private final static int SEQUENCE_BIT = String.valueOf(MAX_SEQUENCE_NUM).length();

    private final static String workerId = "0";

    private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");

    private String noType;

    private final AtomicRangeInteger atomicRangeInteger = new AtomicRangeInteger(0, MAX_SEQUENCE_NUM);

    public static SerialGenerator generator = new SerialGenerator();

    public SerialGenerator() {
    }

    public SerialGenerator(String noType) {
        this.noType = noType;
    }

    public String nextId() {
        // yyyyMMddHHmmss(b)(num)
        StringBuilder sb = new StringBuilder();

        if (StringUtils.hasText(noType)) {
            sb.append(noType);
        }

        // sb.append(DateUtil.getCurrDate("yyyyMMddHHmmss"));
        sb.append(formatter.format(LocalDateTime.now()));
        // System.out.println(" --------- workerId : " + workerId);
        //sb.append(workerId);
        String tmp = atomicRangeInteger.incrAndGet().toString();

        sb.append(getPreZeroNumber3(SEQUENCE_BIT, tmp));
        return sb.toString();
    }

    /**
     * @param prefix 前缀,默认为GD  栗子：GD
     * @param format 日期格式化方式，默认为 yyyyMMdd 栗子：yyyyMMdd
     * @return 栗子：GD202306115353988099
     */
    public static String flowCode(String prefix, String format) {
        if (Objects.isNull(prefix))
            prefix = "GD";
        if (Objects.isNull(format))
            format = "yyyyMMddHHmm";
        String l = IdUtil.getSnowflakeNextIdStr().substring(9);
        return StrUtil.format("{}{}{}", prefix, DateUtil.format(new Date(), format), l);
    }

    public static String getPreZeroNumber3(int num, String str) {
        int strLen = str.length();
        if (strLen < num) {
            for (int i = strLen; i < num; i++) {
                StringBuffer sb = new StringBuffer();
                sb.append("0").append(str);
                str = sb.toString();
            }
        }
        return str;
    }

    public static void main(String[] args) {
        System.out.println(workerId);
        SerialGenerator sg = new SerialGenerator();
        for (int j = 0; j <= 9; j++) {
            new Thread(() -> {
                for (int i = 0; i < MAX_SEQUENCE_NUM + 1; i++) {
                    System.out.println(Thread.currentThread().getName() + " -- " + sg.nextId());
                }
            }).start();
        }
    }
}

class AtomicRangeInteger {
    private final int maxValue;
    private final AtomicInteger atomicInteger;

    public AtomicRangeInteger(final int minValue, final int maxValue) {
        this.atomicInteger = new AtomicInteger(minValue);
        this.maxValue = maxValue;

    }

    public Integer incrAndGet() {
        this.atomicInteger.compareAndSet(this.maxValue, 0);
        final int value = this.atomicInteger.incrementAndGet();
        return value;
    }

}
